﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using Moki;
using Moki.Tests.Model;


namespace Moki.Tests
{
    [TestFixture]
    public class PartialMockSpec
    {
        [TearDown]
        public void TearDown()
        {
            Mock.CleanUp();
        }

        [Test]
        public void When_stubbed_should_return_stub()
        {
            PartialMockTest test = Mock.Create<PartialMockTest>();

            Mock.WhenCalled(() => test.OriginalReturnsTrue()).Returns(false);
            Mock.WhenGet(() => test.ReturnsHello).Returns("Hi");

            Assert.AreEqual(false, test.OriginalReturnsTrue());
            Assert.AreEqual("Hi", test.ReturnsHello);
        }

        [Test]
        public void When_stub_orignal_method_should_return_stub()
        {
            PartialMockTest test = Mock.Create<PartialMockTest>();

            Mock.WhenCalled(() => test.GetSomething()).Returns("works!");

            Assert.AreEqual("works!", test.GetSomething());
        }

        [Test]
        public void When_stub_method_should_return_stub()
        {
            PartialMockTest test = Mock.Create<PartialMockTest>();

            Mock.WhenCalled(() => test.GetSomething()).Returns("works!");

            Assert.AreEqual("works!", test.GetSomething());
        }

        [Test]
        public void When_stub_property_should_return_stub()
        {
            PartialMockTest test = Mock.Create<PartialMockTest>();

            Mock.WhenGet(() => test.ReturnsHello).Returns("Hi");

            Assert.AreEqual("Hi", test.ReturnsHello);
        }

        [Test]
        public void When_called_not_stubbed_should_return_original()
        {
            PartialMockTest test = Mock.Create<PartialMockTest>();

            Mock.WhenCalled(() => test.GetSomethingWithArgs(1)).Returns("one");

            Assert.AreEqual("one", test.CallGetSomethingWithArgs(1));
            Assert.AreEqual("2", test.CallGetSomethingWithArgs(2));
        }

        [Test]
        public void When_not_stubbed_should_return_original()
        {
            PartialMockTest test = Mock.Create<PartialMockTest>();

            Assert.AreEqual(true, test.OriginalReturnsTrue());
            Assert.AreEqual("Hello", test.ReturnsHello);
        }

        [Test]
        public void When_called_original_method_should_return_original()
        {
            PartialMockTest test = Mock.Create<PartialMockTest>();

            Assert.IsTrue(test.OriginalReturnsTrue());
        }

        [Test]
        public void When_called_original_property_should_return_original()
        {
            PartialMockTest test = Mock.Create<PartialMockTest>();

            Assert.AreEqual("Hello", test.ReturnsHello);
        }

        [Test]
        public void When_method_call_other_method_should_be_called()
        {
            PartialMockTest test = Mock.Create<PartialMockTest>();

            test.CallDoMethod();

            Mock.VerifyCalledWithAnyArgs(() => test.Do());
            
            //Verify.WasCalled(() => test.CallDoMethod()); // we can't verify non-virtual method
        }

        [Test]
        public void Inner_implemented_property_get_should_return_mock()
        {
            PartialMockTest test = Mock.Create<PartialMockTest>();
            PartialMockTest result = new PartialMockTest() { IdVirtual = 100 };

            Mock.WhenGet(() => test.ImplementedPropertyReturnsObject.
                ImplementedPropertyReturnsObject.
                ImplementedPropertyReturnsObject).Returns(result);

            Assert.AreEqual(0, test.ImplementedPropertyReturnsObject.IdVirtual);
            Assert.AreEqual(0, test.ImplementedPropertyReturnsObject.ImplementedPropertyReturnsObject.IdVirtual);
            Assert.AreEqual(100, test.ImplementedPropertyReturnsObject.
                ImplementedPropertyReturnsObject.
                ImplementedPropertyReturnsObject.IdVirtual);
        }
    }
}
